<!DOCTYPE HTML>
<html>

<head>
	<link rel="bookmark"  type="image/x-icon"  href="/img/logo.png"/>
	<link rel="shortcut icon" href="/img/logo.png">
	
			    <title>
    Archer`s
    </title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
    <link rel="stylesheet" href="/css/mic_main.css" />
    <link rel="stylesheet" href="/css/dropdownMenu.css" />
    <meta name="keywords" content="Archer,arche2r,Arche2r,Archer的博客" />
    
    	<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
	 
    <noscript>
        <link rel="stylesheet" href="/css/noscript.css" />
    </noscript>
    <style type="text/css">
        body:before {
          content: ' ';
          position: fixed;
          top: 0;
          background: url('/img/bg.jpg') center 0 no-repeat;
          right: 0;
          bottom: 0;
          left: 0;
          background-size: cover; 
        }
    </style>

			    
  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script async type="text/javascript" src="//cdn.bootcss.com/mathjax/2.7.1/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
  


    <script src="/js/jquery.min.js"></script>
    <script src="/js/jquery.scrollex.min.js"></script>
    <script src="/js/jquery.scrolly.min.js"></script>
    <script src="/js/skel.min.js"></script>
    <script src="/js/util.js"></script>
    <script src="/js/main.js"></script>
	
<meta name="generator" content="Hexo 4.2.0"></head>
    
		
<!-- Layouts -->



<!--  代码渲染  -->
<link rel="stylesheet" href="/css/prism_coy.css" />
<link rel="stylesheet" href="/css/typo.css" />
<!-- 文章页 -->
<body class="is-loading">
    <!-- Wrapper 外包 s-->
    <div id="wrapper" class="fade-in">
        <!-- Intro 头部显示 s -->
        <!-- Intro 头部显示 e -->
        <!-- Header 头部logo start -->
        <header id="header">
    <a href="/" class="logo">IT`S ME</a>
</header>
        <!-- Nav 导航条 start -->
        <nav id="nav" class="special" >
            <ul class="menu links" >
			<!-- Homepage  主页  --> 
			<li >
	            <a href="/" rel="nofollow">主页</a>
	        </li>
			<!-- categories_name  分类   --> 
	        
	        <!-- archives  归档   --> 
	        
	        <li class="active">
	            <a href="#s1">归档</a>
	                    <ul class="submenu">
	                        <li>
	                        <a class="archive-link" href="/archives/2022/01/">一月 2022</a></li><li><a class="archive-link" href="/archives/2020/06/">六月 2020</a></li><li><a class="archive-link" href="/archives/2019/08/">八月 2019</a></li><li><a class="archive-link" href="/archives/2019/06/">六月 2019</a></li><li><a class="archive-link" href="/archives/2019/05/">五月 2019</a>
	                    </ul>
	        </li>
	        
	        
		        <!-- Pages 自定义   -->
		        
		        <li>
		            <a href="/gallery/" title="图库">
		                图库
		            </a>
		        </li>
		        


            </ul>
            <!-- icons 图标   -->
			<ul class="icons">
                    
                    <li>
                        <a title="tv" href="https://space.bilibili.com/39520610" target="_blank" rel="noopener">
                            <i class="icon fa fa-tv"></i>
                        </a>
                    </li>
                    
                    <li>
                        <a title="github" href="https://github.com/arche2r" target="_blank" rel="noopener">
                            <i class="icon fa fa-github"></i>
                        </a>
                    </li>
                    
                    <li>
                        <a title="qq" href="tencent://message/?uin=1151147869&Site=&Menu=yes" target="_blank" rel="noopener">
                            <i class="icon fa fa-qq"></i>
                        </a>
                    </li>
                    
			</ul>
</nav>

        <div id="main" >
            <div class ="post_page_title_img" style="height: 25rem;background-image: url(/images/pic/90613/90613.jpg);background-position: center; background-repeat:no-repeat; background-size:cover;-moz-background-size:cover;overflow:hidden;" >
                <a href="#" style="padding: 4rem 4rem 2rem 4rem ;"><h2 >策略模式之异常处理分发</h2></a>
            </div>
            <!-- Post -->
            <div class="typo" style="padding: 3rem;">
                <p><strong><a href="https://www.cnblogs.com/jiujiduilie/p/9191629.html" target="_blank" rel="noopener">策略模式是oop中最著名的设计模式之一，是对方法行为的抽象，可以归类为行为设计模式，也是oop中interface经典的应用。</a></strong></p>
<p>策略模式就是对某个行为进行了抽象,可以根据不同的动作带来不同的处理逻辑,它比责任链模式简单且实用,且颇为常见.</p>
<p><img src="/images/pic/90613/90613-1.gif" alt="img"></p>
<p>常见的策略模式UML类图如上↑↑↑,其中主要有以下三个角色:</p>
<pre><code>环境(Context)角色：持有一个Strategy的引用。

抽象策略(Strategy)角色：这是一个抽象角色，通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

具体策略(ConcreteStrategy)角色：包装了相关的具体算法或行为。</code></pre><p>本次基于SpringMVC的统一异常处理来进行代码的演示:</p>
<p> 首先我们模拟一个异常的发生,这里使用自定义异常,</p>
<p>自定义异常类如下:</p>
<pre><code>public class SysException extends Exception {
    public SysException(String message) {
        super(message);
    }
}</code></pre><p>逮住它:</p>
<pre><code>public String tryException() throws SysException {
    try {
        //故意制造异常
        int i= 1/0;
    } catch (Exception e) {
        throw new SysException(&quot;不好意思,语文老师教的数学课~&quot;);
    }
    return &quot;redirect:index.html&quot;;
}</code></pre><p>在处理类中,一旦异常较多会引发及其多的if…else…,这里我们用采用策略模式来分解它</p>
<pre><code>//把自己交给Spring管理
@Component
public class SysExceptionHandler implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        //System.out.println(&quot;该异常的类是&quot;+e.getClass());
        //在此处使用策略模式,先根据不同的class从异常处理环境中获取对应的处理器
        Strategy strategy = ExceptionHandlerContext.ContextFunc(e.getClass());
        //通过处理器来处理不同的异常
        ActionResult result = strategy.StrategyFunc(e);
        //对返回数据进行编码
        httpServletResponse.setContentType(&quot;application/json;charset=utf-8&quot;);
        try {
            //将数据写回
            @Cleanup PrintWriter writer = httpServletResponse.getWriter();
            writer.write(JsonUtils.object2Json(result));
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return new ModelAndView();
    }
}</code></pre><p>首先是环境(Context)角色,这里我们在类中不止持有一个引用,而是拿了一堆~</p>
<p>ExceptionHandlerContext:</p>
<pre><code>public class ExceptionHandlerContext {
    //存放一个map集合,里面有不同异常对应的策略实现
    private static Map&lt;Class,Strategy&gt; exceptionStrategy;
    //提供set方法供Spring注入
    public void setExceptionStrategy(Map&lt;Class, Strategy&gt; exceptionStrategy) {
        ExceptionHandlerContext.exceptionStrategy = exceptionStrategy;
    }
    public static Strategy ContextFunc(Class clazz){
        //通过传入的异常全限定名取出不同的策略实现实例
        Strategy strategy = exceptionStrategy.get(clazz);
        //如果没有自定义的实现就使用默认的
        if (strategy == null){
            return new DefaultStrategy();
        }
        return strategy;
    }
}</code></pre><p>为了保证map不是null,要在applicationContext.xml中配置一下,记得开注解扫描</p>
<pre><code>&lt;bean class=&quot;com.archer.StrategyPattern.ExceptionHandlerContext&quot; id=&quot;exceptionHandlerContext&quot; scope=&quot;singleton&quot;&gt;
   &lt;property name=&quot;exceptionStrategy&quot;&gt;
     &lt;map&gt;
       &lt;entry key=&quot;com.archer.exception.SysException&quot; value-ref=&quot;sysExceptionStrategy&quot; /&gt;
       &lt;entry key=&quot;com.archer.exception.tttException&quot; value-ref=&quot;tttExceptionStrategy&quot;/&gt;
        &lt;/map&gt;
    &lt;/property&gt;
&lt;/bean&gt;</code></pre><p>然后看一下返回的是什么↓</p>
<p>抽象策略(Strategy)角色:</p>
<pre><code>public interface Strategy {
    /**
     * @Description: TODO 定义异常处理策略实现
     * @author:      Archer
     * @Date:        2019/6/13 10:41:22
     * @param:       e 抓到的异常信息
     * @return:      com.archer.pojo.ActionResult 返回值是ActionResult类型,用来存储返回到页面的信息bean
     */
    ActionResult StrategyFunc(Exception e);
}</code></pre><p>还有 具体策略(ConcreteStrategy)角色↓</p>
<p>默认的策略实现DefaultStrategy:</p>
<pre><code>public class DefaultStrategy implements Strategy {
    @Override
    public ActionResult StrategyFunc(Exception e) {
        ActionResult result = new ActionResult();
        result.setMsg(&quot;默认来的消息  +  &quot;+e.getMessage());
        result.setFlag(false);
        return result;
    }
}</code></pre><p>自定义实现SysExceptionStrategy:</p>
<pre><code>//把自己交给Spring管理
@Component
public class SysExceptionStrategy implements Strategy {
    @Override
    public ActionResult StrategyFunc(Exception e) {
        ActionResult result = new ActionResult();
        result.setMsg(&quot;SysExceptionStrategy  +  &quot;+e.getMessage());
        result.setFlag(false);
        return result;
    }
}</code></pre><p>经过具体的策略实现后返回ActionResult对象,将其序列化为json格式后返回即可~<br>​​</p>
<p>结果如图:</p>
<p><img src="/images/pic/90613/90613-2.png" alt="img"></p>

            </div>

            <!-- Post Comments -->
            

        </div>
        <!-- Copyright 版权 start -->
                <div id="copyright">
                <span id="busuanzi_container_site_pv"><span id="busuanzi_value_site_pv"></span>次的回眸</span>
<span>·</span>
				<span id="busuanzi_container_site_pv"> 2022 </span> 

        </div>
    </div>
</body>



 	
</html>
